﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using NativeWiFiLibrary;
using System.Windows.Media.Animation;
using System.Threading;
using WiFiChannelSpread.GoogleApi;
using System.ComponentModel;

namespace WiFiChannelSpread
{
    /// <summary>
    /// Interaction logic for AccessPointControl.xaml
    /// </summary>
    public partial class AccessPointControl : UserControl
    {
        public AccessPoint MyAccessPoint { get; set; }
        public Network MyNetwork { get { return this.MyAccessPoint.Network; } }

        public bool IsConnected { get { return false; } }

        public event StatusChangeEventHandler StatusChanged;
        public event ExceptionEventHandler ExceptionHandler;

        public Brush HighlightColor
        {
            get
            {
                if (MyNetwork.IsConnected)
                {
                    return new SolidColorBrush(Color.FromRgb(0, 176, 0));
                }
                else if (MyNetwork.HasProfile)
                {
                    return new SolidColorBrush(Color.FromRgb(80, 80, 250));
                }
                else
                {
                    return Brushes.Silver;
                }
            }
        }

        public double OpacityFromSignalStrength
        {
            get
            {
                return 0.3 + (MyAccessPoint.LinkQuality / 150.0);
            }
        }

        public double HeightFromSignalStrength
        {
            get { return 35 + MyAccessPoint.LinkQuality; }
        }

        public string LinkQualityText { get { return MyAccessPoint.LinkQuality.ToString() + "%"; } }

        public string PhyTypeText
        {
            get
            {
                string standard;
                switch (MyAccessPoint.PhyType)
                {
                    case PhyType.Hrdsss: standard = "802.11b"; break;
                    case PhyType.Erp: standard = "802.11g"; break;
                    case PhyType.Ht: standard = "802.11n"; break;
                    default: standard = MyAccessPoint.PhyType.ToString(); break;
                }

                return standard;
            }
        }

        public string AccessPointTitle
        {
            get { return string.IsNullOrEmpty(MyNetwork.Ssid) ? "* Anonymous" : MyNetwork.Ssid; }
        }

        public AccessPointControl(AccessPoint accessPoint)
        {
            this.MyAccessPoint = accessPoint;

            InitializeComponent();
            this.Loaded += new RoutedEventHandler(AccessPointControl_Loaded);
        }

        void AccessPointControl_Loaded(object sender, RoutedEventArgs e)
        {
            LockImage.Visibility = this.MyNetwork.IsSecurityEnabled ? Visibility.Visible : Visibility.Collapsed;
            UnlockImage.Visibility = this.MyNetwork.IsSecurityEnabled ? Visibility.Collapsed : Visibility.Visible;

            ThreadPool.QueueUserWorkItem((s) => { LoadGeolocation(); });
        }

        private void LoadGeolocation()
        {
            bool hasLocation = false, hasError = false;

            try
            {
                Location location = GeolocationApi.GetGeolocationOfWiFiTower(MyAccessPoint.MacAddress, MyAccessPoint.Ssid, true);
                if (location != null && !string.IsNullOrEmpty(location.latitude))
                {
                    hasLocation = true;
                }

                MyAccessPoint.Geolocation = location;
            }
            catch (Exception ex)
            {
                hasError = true;
                MyAccessPoint.Geolocation = ex;
                Dispatcher.BeginInvoke(new Action(() => { ExceptionHandler(this, "Failed to load geolocation.", ex); }));
            }

            if (hasLocation)
            {
                //Dispatcher.BeginInvoke(new Action(() => { GlobeUnknownImage.Visibility = Visibility.Collapsed; GlobeImage.Visibility = Visibility.Visible; }));
                Dispatcher.BeginInvoke(new Action(() => { AnimationHelper.FadeIn(GlobeImage, 0.8); }));
            }
            else if (!hasError)
            {
                Dispatcher.BeginInvoke(new Action(() => { AnimationHelper.FadeIn(GlobeUnknownImage, 0.6); }));
            }
        }

        private void MyRoot_MouseEnter(object sender, MouseEventArgs e)
        {
            AnimationHelper.StartDoubleAnimation(BackgroundSquare, Control.OpacityProperty, 0.9);
            LabelName.Opacity = 1;
        }

        private void MyRoot_MouseLeave(object sender, MouseEventArgs e)
        {
            AnimationHelper.StartDoubleAnimation(BackgroundSquare, Control.OpacityProperty, OpacityFromSignalStrength);
            LabelName.Opacity = OpacityFromSignalStrength;
        }

        private void MyRoot_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (this.StatusChanged != null)
            {
                this.StatusChanged(this, StatusChangeAction.PauseUpdates);
            }

            double angle = 45;
            DependencyProperty targetProperty;
            if (MyAccessPoint.Channel <= 4)
            {
                targetProperty = Planerator.RotationYProperty;
                angle = 45;
            }
            else if (MyAccessPoint.Channel >= 10)
            {
                targetProperty = Planerator.RotationYProperty;
                angle = -45;
            }
            else
            {
                targetProperty = Planerator.RotationXProperty;
                angle = -45;
            }

            AnimationHelper.StartDoubleAnimation(
                Planerator1,
                targetProperty,
                angle);

            NetworkDetailsControl ndc = new NetworkDetailsControl(this.MyAccessPoint);
            ndc.StatusChanged += new StatusChangeEventHandler(ndc_StatusChanged);
            ndc.ExceptionHandler += new ExceptionEventHandler(ndc_ExceptionHandler);
            if (this.Parent != null)
            {
                ((this.Parent as FrameworkElement).Parent as Panel).Children.Add(ndc);
            }
        }

        void ndc_ExceptionHandler(object sender, string message, Exception exception)
        {
            AnimationHelper.StartDoubleAnimation(Planerator1, Planerator.RotationXProperty, 0);
            AnimationHelper.StartDoubleAnimation(Planerator1, Planerator.RotationYProperty, 0);

            if (this.StatusChanged != null)
            {
                this.StatusChanged(this, StatusChangeAction.UpdateAsap);
            }

            this.ExceptionHandler(this, message, exception);
        }

        void ndc_StatusChanged(object sender, StatusChangeAction requiredAction)
        {
            AnimationHelper.StartDoubleAnimation(Planerator1, Planerator.RotationXProperty, 0);
            AnimationHelper.StartDoubleAnimation(Planerator1, Planerator.RotationYProperty, 0,
                () =>
                {
                    if (this.StatusChanged != null)
                    {
                        this.StatusChanged(this, requiredAction);
                    }
                });
        }
    }
}
